home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / hplip / base / models.py < prev    next >
Text File  |  2008-10-13  |  12KB  |  416 lines

  1. # -*- coding: utf-8 -*-
  2. #
  3. # (c) Copyright 2003-2008 Hewlett-Packard Development Company, L.P.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  18. #
  19. # Author: Don Welch
  20.  
  21. from base.g import *
  22. from base import utils
  23.  
  24. import os.path
  25. import re
  26. import glob
  27.  
  28. pat_prod_num = re.compile("""(\d+)""", re.I)
  29.  
  30. TYPE_UNKNOWN = 0
  31. TYPE_STRING = 1
  32. TYPE_STR = 1
  33. TYPE_LIST = 2
  34. TYPE_BOOL = 3
  35. TYPE_INT = 4
  36. TYPE_HEX = 5
  37. TYPE_BITFIELD = 6
  38.  
  39. TECH_CLASSES = [
  40.     "Undefined", # This will show an error (and its the default)
  41.     "Unsupported", # This is for unsupported models, and it will not show an error
  42.     "Postscript",
  43.     "DJGenericVIP",
  44.     #"PSB9100", not used on HPLIP
  45.     "LJMono",
  46.     "LJColor",
  47.     "LJFastRaster",
  48.     "LJJetReady",
  49.     "DJ350",
  50.     #"DJ400", not used on HPLIP
  51.     "DJ540",
  52.     "DJ600",
  53.     "DJ6xx",
  54.     "DJ6xxPhoto",
  55.     "DJ630",
  56.     #"DJ660", not used in HPLIP
  57.     "DJ8xx",
  58.     "DJ8x5",
  59.     "DJ850",
  60.     "DJ890",
  61.     "DJ9xx",
  62.     "DJ9xxVIP",
  63.     "DJ3600",
  64.     "DJ3320",
  65.     "DJ4100",
  66.     "AP2xxx",
  67.     "AP21xx",
  68.     "AP2560",
  69.     "PSP100",
  70.     "PSP470",
  71.     "LJZjsMono",
  72.     "LJZjsColor",
  73.     "LJm1005",
  74.     "QuickConnect",
  75.     "DJ55xx",
  76.     "OJProKx50",
  77. ]
  78.  
  79. TECH_CLASSES.sort()
  80.  
  81. TECH_CLASS_PDLS = {
  82.     #"Undefined"    : '?',
  83.     "Postscript"   : 'ps',
  84.     "DJGenericVIP" : 'pcl3',
  85.     #"PSB9100"      : 'pcl3',
  86.     "LJMono"       : 'pcl3',
  87.     "LJColor"      : 'pcl3',
  88.     "LJFastRaster" : 'pclxl',
  89.     "LJJetReady"   : 'pclxl',
  90.     "DJ350"        : 'pcl3', 
  91.     #"DJ400"        : 'pcl3',
  92.     "DJ540"        : 'pcl3',
  93.     "DJ600"        : 'pcl3',
  94.     "DJ6xx"        : 'pcl3',
  95.     "DJ6xxPhoto"   : 'pcl3',
  96.     "DJ630"        : 'pcl3',
  97.     #"DJ660"        : 'pcl3',
  98.     "DJ8xx"        : 'pcl3',
  99.     "DJ8x5"        : 'pcl3',
  100.     "DJ850"        : 'pcl3',
  101.     "DJ890"        : 'pcl3',
  102.     "DJ9xx"        : 'pcl3',
  103.     "DJ9xxVIP"     : 'pcl3',
  104.     "DJ3600"       : 'lidil',
  105.     "DJ3320"       : 'lidil',
  106.     "DJ4100"       : 'lidil',
  107.     "AP2xxx"       : 'pcl3',
  108.     "AP21xx"       : 'pcl3',
  109.     "AP2560"       : 'pcl3',
  110.     "PSP100"       : 'pcl3',
  111.     "PSP470"       : 'pcl3',
  112.     "LJZjsMono"    : 'zjs',
  113.     "LJZjsColor"   : 'zjs',
  114.     "LJm1005"      : 'zxstream',
  115.     "QuickConnect" : 'jpeg',
  116.     "DJ55xx"       : 'pcl3',
  117.     "OJProKx50"    : 'pcl3',
  118. }
  119.  
  120.  
  121. TECH_SUBCLASSES = [
  122.     "LargeFormatSuperB",
  123.     "LargeFormatA3",
  124.     "CoverMedia", # 3425
  125.     "FullBleed",
  126.     "Duplex",
  127.     "Normal",
  128.     "Apollo2000",
  129.     "Apollo2200",
  130.     "Apollo2500",
  131.     "NoPhotoMode",
  132.     "NoPhotoBestHiresModes",
  133.     "No1200dpiNoSensor",
  134.     "NoFullBleed",
  135.     "4x6FullBleed",
  136.     "300dpiOnly",  # LaserJet 4L
  137.     "GrayscaleOnly", # DJ540
  138. ]
  139.  
  140. TECH_SUBCLASSES.sort()
  141.  
  142.  
  143. # Items will be capitalized unless in this dict
  144. MODEL_UI_REPLACEMENTS = {'laserjet'   : 'LaserJet',
  145.                           'psc'        : 'PSC',
  146.                           'officejet'  : 'Officejet',
  147.                           'deskjet'    : 'Deskjet',
  148.                           'hp'         : 'HP',
  149.                           'business'   : 'Business',
  150.                           'inkjet'     : 'Inkjet',
  151.                           'photosmart' : 'Photosmart',
  152.                           'color'      : 'Color',
  153.                           'series'     : 'series',
  154.                           'printer'    : 'Printer',
  155.                           'mfp'        : 'MFP',
  156.                           'mopier'     : 'Mopier',
  157.                           'pro'        : 'Pro',
  158.                           'apollo'     : 'Apollo',
  159.                         }
  160.         
  161.         
  162. def normalizeModelUIName(model):
  163.     ml = model.lower().strip()
  164.     
  165.     if 'apollo' in ml:
  166.         z = ml.replace('_', ' ')
  167.     else:
  168.         if ml.startswith("hp"):
  169.             z = ml[3:].replace('_', ' ')
  170.         else:
  171.             z = ml.replace('_', ' ')
  172.     
  173.     y = []
  174.     for x in z.split():
  175.         if pat_prod_num.search(x): # don't cap items like cp1700dn
  176.             y.append(x)
  177.         else:
  178.             y.append(MODEL_UI_REPLACEMENTS.get(x, x.capitalize()))
  179.  
  180.     if 'apollo' in ml:
  181.         return ' '.join(y)
  182.     else:
  183.         return "HP " + ' '.join(y)
  184.         
  185.  
  186. def normalizeModelName(model):
  187.     return utils.xstrip(model.replace(' ', '_').replace('__', '_').replace('~','').replace('/', '_'), '_')
  188.         
  189.  
  190. class ModelData:
  191.     def __init__(self, root_path=None):
  192.         if root_path is None:
  193.             self.root_path = prop.models_dir
  194.         else:
  195.             self.root_path = root_path
  196.  
  197.         self.__cache = {}
  198.         self.reset_includes()
  199.         self.sec = re.compile(r'^\[(.*)\]')
  200.         self.inc = re.compile(r'^\%include (.*)', re.IGNORECASE)
  201.         self.inc_line = re.compile(r'^\%(.*)\%')
  202.         self.eq = re.compile(r'^([^=]+)=(.*)')
  203.         
  204.         self.FIELD_TYPES = {
  205.             'align-type' : TYPE_INT,
  206.             'clean-type' : TYPE_INT,
  207.             'color-cal-type' : TYPE_INT,
  208.             'copy-type' : TYPE_INT,
  209.             'embedded-server-type' : TYPE_INT,
  210.             'fax-type' : TYPE_INT,
  211.             'fw-download' : TYPE_BOOL,
  212.             'icon' : TYPE_STR,
  213.             'io-mfp-mode' : TYPE_INT,
  214.             'io-mode' : TYPE_INT,
  215.             'io-support' : TYPE_BITFIELD,
  216.             'linefeed-cal-type' : TYPE_INT,
  217.             'panel-check-type' : TYPE_INT,
  218.             'pcard-type' : TYPE_INT,
  219.             'plugin' : TYPE_INT,
  220.             'power-settings': TYPE_INT,
  221.             'pq-diag-type' : TYPE_INT,
  222.             'r-type' : TYPE_INT,
  223.             'scan-style' : TYPE_INT,
  224.             'scan-type' : TYPE_INT,
  225.             'status-battery-check' : TYPE_INT,
  226.             'status-dynamic-counters' : TYPE_INT,
  227.             'status-type' : TYPE_INT,
  228.             'support-released' : TYPE_BOOL,
  229.             'support-type' : TYPE_INT,
  230.             'support-ver' : TYPE_STR,
  231.             'tech-class' : TYPE_LIST,
  232.             'tech-subclass' : TYPE_LIST,
  233.             'tech-type' : TYPE_INT,
  234.             'usb-pid' : TYPE_HEX,
  235.             'usb-vid' : TYPE_HEX,
  236.             'job-storage' : TYPE_INT,
  237.             }
  238.             
  239.         self.RE_FIELD_TYPES = {
  240.             re.compile('r(\d+)-agent(\d+)-kind', re.IGNORECASE) : TYPE_INT,
  241.             re.compile('r(\d+)-agent(\d+)-type', re.IGNORECASE) : TYPE_INT,
  242.             re.compile('r(\d+)-agent(\d+)-sku', re.IGNORECASE) : TYPE_STR,
  243.             re.compile('model(\d+)', re.IGNORECASE) : TYPE_STR,
  244.             }
  245.             
  246.         self.TYPE_CACHE = {}
  247.             
  248.           
  249.  
  250.     def read_all_files(self, unreleased=True):
  251.         released_dat = os.path.join(self.root_path, "models.dat")
  252.         log.debug("Reading file: %s" % released_dat)
  253.         self.read_section(released_dat)
  254.  
  255.         unreleased_dir = os.path.join(self.root_path, 'unreleased')
  256.         if unreleased and os.path.exists(unreleased_dir):
  257.             unreleased_dat = os.path.join(self.root_path, "unreleased", "unreleased.dat")
  258.             log.debug("Reading file: %s" % unreleased_dat)
  259.             self.read_section(unreleased_dat)
  260.  
  261.         return self.__cache
  262.  
  263.     def read_section(self, filename, section=None, is_include=False): # section==None, read all sections
  264.         found, in_section = False, False
  265.  
  266.         if section is not None:
  267.             section = section.lower()
  268.  
  269.             if is_include:
  270.                 log.debug("Searching for include [%s] in file %s" % (section, filename))
  271.             else:
  272.                 log.debug("Searching for section [%s] in file %s" % (section, filename))
  273.  
  274.         if is_include:
  275.             cache = self.__includes
  276.         else:
  277.             cache = self.__cache
  278.  
  279.         try:
  280.             fd = file(filename)
  281.         except IOError, e:
  282.             log.error("I/O Error: %s (%s)" % (filename, e.strerror))
  283.             return False
  284.  
  285.         while True:
  286.             line = fd.readline()
  287.  
  288.             if not line:
  289.                 break
  290.  
  291.             if line[0] in ('#', ';'):
  292.                 continue
  293.  
  294.             if line[0] == '[':
  295.                 if in_section and section is not None:
  296.                     break
  297.  
  298.                 match = self.sec.search(line)
  299.  
  300.                 if match is not None:
  301.                     in_section = True
  302.  
  303.                     read_section = match.group(1).lower()
  304.  
  305.                     if section is not None:
  306.                         found = in_section = (read_section == section)
  307.  
  308.                     if in_section:
  309.                         if section is not None:
  310.                             log.debug("Found section [%s] in file %s" % (read_section, filename))
  311.  
  312.                         cache[read_section] = {}
  313.  
  314.                 continue
  315.  
  316.             if line[0] == '%':
  317.                 match = self.inc.match(line)
  318.  
  319.                 if match is not None:
  320.                     inc_file = match.group(1)
  321.                     log.debug("Found include file directive: %%include %s" % inc_file)
  322.                     self.__include_files.append(os.path.join(os.path.dirname(filename), inc_file))
  323.                     continue
  324.  
  325.                 if in_section:
  326.                     match = self.inc_line.match(line)
  327.  
  328.                     if match is not None: 
  329.                         inc_sect = match.group(1)
  330.                         log.debug("Found include directive %%%s%%" % inc_sect)
  331.  
  332.                         try:
  333.                             self.__includes[inc_sect]
  334.                         except KeyError:
  335.                             for inc in self.__include_files:
  336.  
  337.                                 if self.read_section(inc, inc_sect, True):
  338.                                     break
  339.                             else:
  340.                                 log.error("Include %%%s%% not found." % inc_sect)
  341.  
  342.  
  343.             if in_section:
  344.                 match = self.eq.search(line)
  345.  
  346.                 if match is not None:
  347.                     key = match.group(1)
  348.                     value = match.group(2)
  349.                     typ = self.get_data_type(key)
  350.                     
  351.                     if  typ in (TYPE_BITFIELD, TYPE_INT):
  352.                         value = int(value)
  353.                     
  354.                     elif typ == TYPE_BOOL:
  355.                         #value = utils.to_bool(value)
  356.                         value = int(value)
  357.                         
  358.                     elif typ == TYPE_LIST:
  359.                         value = [x for x in value.split(',') if x]
  360.                         
  361.                     cache[read_section][key] = value
  362.  
  363.         fd.close()
  364.         return found
  365.  
  366.     def reset_includes(self):
  367.         self.__include_files = []
  368.         self.__includes = {}
  369.  
  370.  
  371.     def __getitem__(self, model):
  372.         model = model.lower()
  373.  
  374.         try:
  375.             return self.__cache[model]
  376.         except:
  377.             log.debug("Cache miss: %s" % model)
  378.  
  379.             released_dat = os.path.join(self.root_path, "models.dat")
  380.             log.debug("Reading file: %s" % released_dat)
  381.  
  382.             if self.read_section(released_dat, model):
  383.                 return self.__cache[model]
  384.  
  385.             unreleased_dir = os.path.join(self.root_path, 'unreleased')
  386.  
  387.             if os.path.exists(unreleased_dir):
  388.                 unreleased_dat = os.path.join(self.root_path, "unreleased", "unreleased.dat")
  389.                 log.debug("Reading file: %s" % unreleased_dat)
  390.  
  391.                 if self.read_section(unreleased_dat, model):
  392.                     return self.__cache[model]
  393.  
  394.             return {}
  395.  
  396.  
  397.     def all_models(self):
  398.         return self.__cache
  399.         
  400.     def get_data_type(self, key):
  401.         try:
  402.             return self.FIELD_TYPES[key]
  403.         except KeyError:
  404.             try:
  405.                 return self.TYPE_CACHE[key]
  406.             except KeyError:
  407.                 for pat, typ in self.RE_FIELD_TYPES.items():
  408.                     match = pat.match(key)
  409.                     if match is not None:
  410.                         self.TYPE_CACHE[key] = typ
  411.                         return typ
  412.         
  413.         return TYPE_STR
  414.     
  415.  
  416.